package com.ciccwm.log.util;

import org.junit.jupiter.api.Test;

import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 链路ID工具类测试.
 */
class TraceIdUtilTest {

    /**
     * 测试生成链路ID.
     * 验证生成的链路ID不为空且长度为32.
     */
    @Test
    void testGenerateTraceId() {
        TraceIdUtil.removeTraceId();
        String traceId = TraceIdUtil.generateTraceId();
        Assertions.assertNotNull(traceId);
        Assertions.assertEquals(32, traceId.length());
        TraceIdUtil.removeTraceId();
    }

    /**
     * 测试获取和设置链路ID.
     * 验证设置的链路ID可以被正确获取.
     */
    @Test
    void testGetAndSetTraceId() {
        TraceIdUtil.removeTraceId();
        String traceId = TraceIdUtil.generateTraceId();
        TraceIdUtil.setTraceId(traceId);
        Assertions.assertEquals(traceId, TraceIdUtil.getTraceId());
        TraceIdUtil.removeTraceId();
    }

    /**
     * 测试移除链路ID.
     * 验证移除链路ID后返回null.
     */
    @Test
    void testRemoveTraceId() {
        TraceIdUtil.removeTraceId();
        String traceId = TraceIdUtil.generateTraceId();
        TraceIdUtil.setTraceId(traceId);
        TraceIdUtil.removeTraceId();
        Assertions.assertNull(TraceIdUtil.getTraceId());
    }

    /**
     * 测试在Runnable中执行带链路ID的操作.
     * 验证在新线程中可以正确获取链路ID，并在执行完后被清理.
     */
    @Test
    void testExecuteWithTraceIdRunnable() {
        TraceIdUtil.removeTraceId();
        String traceId = TraceIdUtil.generateTraceId();
        AtomicReference<String> threadTraceId = new AtomicReference<>();

        TraceIdUtil.executeWithTraceId(traceId, () -> {
            threadTraceId.set(TraceIdUtil.getTraceId());
        });

        Assertions.assertEquals(traceId, threadTraceId.get());
        Assertions.assertNull(TraceIdUtil.getTraceId());
        TraceIdUtil.removeTraceId();
    }

    /**
     * 测试在Supplier中执行带链路ID的操作.
     * 验证在新线程中可以正确获取链路ID，并返回预期结果，且在执行完后被清理.
     */
    @Test
    void testExecuteWithTraceIdSupplier() {
        TraceIdUtil.removeTraceId();
        String traceId = TraceIdUtil.generateTraceId();
        AtomicReference<String> threadTraceId = new AtomicReference<>();

        String result = TraceIdUtil.executeWithTraceId(traceId, () -> {
            threadTraceId.set(TraceIdUtil.getTraceId());
            return "test";
        });

        Assertions.assertEquals("test", result);
        Assertions.assertEquals(traceId, threadTraceId.get());
        Assertions.assertNull(TraceIdUtil.getTraceId());
        TraceIdUtil.removeTraceId();
    }
} 
